#include "Plateau_private.h"

#include "CasePause.h"
#include "SettingsManager.h"
#include "common.h"

/* Constructor */
Plateau* newPlateau(Jeu* jeu){
	Plateau* p;
	
	p = emalloc(sizeof(Plateau));
	if(p == NULL) return NULL;
	
	plateauSetJeu(p,jeu);
	plateauSetCases(p,newList());
	return p;
}

/* Destructor */
void deletePlateau(Plateau* p){
	
	deleteList(plateauGetCases(p));
	
	
}

typedef int (*TRYCASE)(Plateau* plateau,int* caseLeft);

int tryCasePause(Plateau* plateau,int* caseLeft){
	if((*caseLeft) > 0){
		(*caseLeft)--;
		newCasePause(plateau);
		return 1;
	}
	return 0;
}

int tryCaseEpreuve(Plateau* plateau,int* caseLeft){
	if((*caseLeft) > 0){
		(*caseLeft)--;
		newCasePause(plateau); /* TODO : newCaseEpreuve */
		return 1;
	}
	return 0;
}

int tryCaseMonstre(Plateau* plateau,int* caseLeft){
	if((*caseLeft) > 0){
		(*caseLeft)--;
		newCasePause(plateau); /* TODO : newCaseMonstre */
		return 1;
	}
	return 0;
}

void plateauInit(Plateau* plateau){
	int i;
	TRYCASE addCase[3];
	int caseLeft[3];
	int nbCases;
	int casenum;
	
	addCase[0] = tryCasePause;
	addCase[1] = tryCaseEpreuve;
	addCase[2] = tryCaseMonstre;
	
	nbCases = smGetNbCases() - 2;
	caseLeft[0] = (int)(nbCases/20.0 * 4.0); /* casePause */
	nbCases -= caseLeft[0];
	caseLeft[1] = (int)(nbCases/16.0 * 8.0); /* caseEpreuve */
	nbCases -= caseLeft[1];
	caseLeft[2] = nbCases;
	
	nbCases = smGetNbCases() - 2;
	for(i = 1; i <= nbCases; i++){
		if(i == 0)
			newCasePause(plateau); /* newCaseDepart(plateau); */
		else if(i == nbCases)
			newCasePause(plateau); /* newCaseArrivee(plateau); */
		else{
			casenum = commonRand(3);
			while(!addCase[casenum](plateau,&caseLeft[casenum]))
				casenum = (casenum + 1) % 3;
		}
	}
	
}
/* Getters */
Jeu* plateauGetJeu(Plateau* plateau){
	if(plateau == NULL) return NULL;
	
	return plateau->jeu;
}

List* plateauGetCases(Plateau* plateau){
	eassert(plateau != NULL);
	
	return plateau->cases;
}

/* Settlers */
void plateauSetJeu(Plateau* plateau,Jeu* jeu){
	if(plateau == NULL) return;
	
	plateau->jeu = jeu;
	
	if(jeu != NULL && jeuGetPlateau(jeu) != plateau)
		jeuSetPlateau(jeu,plateau);

}

void plateauSetCases(Plateau* plateau,List* cases){
	eassert(plateau != NULL);
	
	plateau->cases = cases;
}

/* méthodes */
int plateauPlacerEn(Plateau* plateau, Case* c,Personnage* perso){
	eassert(plateau != NULL);
	eassert(c != NULL);
	eassert(perso != NULL);
	
	if(caseGetPlateau(c) != plateau || 
			caseGetPlateau(persoGetCase(perso)) != plateau)
		return 0;
	
	/* On vérifie que la case c ne contienne pas déja le personnage */
	if(listPosOf(caseGetPersos(c),perso) == LIST_INVALIDPOS)
		listInsertLast(caseGetPersos(c),perso);
	
	/* On regarde si le personnage est déja sur la case c */
	if(persoGetCase(perso) != c){
		listRem(caseGetPersos(persoGetCase(perso)),perso);
		persoSetCase(perso,c);
	}
	
	return 1;
}

Case* plateauAvancer(Plateau* plateau,Personnage* perso,int nbCases){
	Case* c;
	List* cases;
	int cPos;
	
	eassert(plateau != NULL);
	eassert(perso != NULL);
	
	if(nbCases == 0) return persoGetCase(perso);
	
	cases = plateauGetCases(plateau);
	c = persoGetCase(perso);
	cPos = listPosOf(cases,c); 	/* TODO: Tester listPosOf dans testList */
	if((unsigned int)cPos == LIST_INVALIDPOS) return NULL;
	
	cPos += nbCases;
	cPos = (cPos < listGetSize(cases))?cPos:listGetSize(cases)-1;
	c = listGetAt(cases,cPos);
	
	plateauPlacerEn(plateau,c,perso);
	
	return c;
}

Case* plateauGetCaseDepart(Plateau* plateau){
	eassert(plateau != NULL);

	return listGetFirst(plateauGetCases(plateau));
}

int plateauHasCase(Plateau* plateau,Case* c){
	eassert(plateau != NULL);
	
	return (listPosOf(plateauGetCases(plateau),c) != LIST_INVALIDPOS);
}

void plateauAddDebutCase(Plateau* plateau,Case* c){
	listInsertFirst(plateauGetCases(plateau),c);
}
